﻿<style>
    .form-editor {
        color: #000 !important; /* Ignore themes for this demo */
    }

    .form-row {
        border: 1px dashed red;
        border-radius: .5em;
        background-color: #fff;
        padding: 1em;
        display: flex;
        gap: 1em;
    }

    .form-column {
        flex: 1;
        border: 2px dashed orange;
        border-radius: .5em;
        min-height: 5em;
        padding: .5rem;
    }

    .empty-zone {
        width: 100%;
        min-height: 50px;
        background-color: yellow;
        height: 100%;
    }

    .form-element {
        border: 1px solid green;
        border-radius: .5em;
        padding: 1rem;
    }

    .form-editor-flex {
        display: flex;
        flex-direction: column;
        gap: .5rem;
    }
</style>
<div class="form-editor">
    <FluentDragContainer TItem="FormRow" OnDropEnd="OnRowDropEnd">
        <FluentDragContainer TItem="FormColumn" OnDropEnd="OnColumnDropEnd">
            <FluentDragContainer TItem="FormElement" OnDropEnd="OnDropElement" Class="form-editor-flex">
                @foreach (var row in _testForm.Rows)
                {
                    <FluentDropZone StopPropagation="true" Item="row" Class="form-row" Draggable="true" Droppable="true">
                        <span>Row: @row.RowId</span>
                        @if (row.Columns.Count == 0)
                        {
                            <FluentDropZone StopPropagation="true" Data="@row" TItem="FormColumn" Class="empty-zone" Draggable="false" Droppable="true" />
                        }
                        else
                        {
                            @foreach (var column in row.Columns)
                            {
                                <FluentDropZone StopPropagation="true" Item="column" Data="@row" Class="form-column form-editor-flex" Draggable="true" Droppable="true">
                                    <span>Column: @column.ColumnId</span>
                                    @if (column.Elements.Count == 0)
                                    {
                                        <FluentDropZone StopPropagation="true" Data="@column" TItem="FormElement" Class="empty-zone" Draggable="false" Droppable="true" />
                                    }
                                    else
                                    {
                                        @foreach (var element in column.Elements)
                                        {
                                            <FluentDropZone StopPropagation="true" Item="element" Data="@column" Class="form-element" Draggable="true" Droppable="true">
                                                <span>Element: @element.ElementId</span>
                                            </FluentDropZone>
                                        }
                                    }
                                </FluentDropZone>
                            }
                        }
                    </FluentDropZone>
                }
            </FluentDragContainer>
        </FluentDragContainer>
    </FluentDragContainer>
</div>

@code {
    private Form _testForm;
    
    public DragDropNested()
    {
        _testForm = new Form();

        var rows = Enumerable.Range(1, 6)
                             .Select(id => new FormRow { RowId = id })
                             .ToList();

        var columns = Enumerable.Range(1, 9)
                                .Select(id => new FormColumn { ColumnId = id })
                                .ToList();

        var elementMap = new Dictionary<int, int>
        {
            { 1, 2 },
            { 2, 1 },
            { 3, 3 },
            { 4, 0 },
            { 5, 2 },
            { 6, 1 },
            { 7, 0 },
            { 8, 1 },
            { 9, 0 }
        };

        int elementIdCounter = 1;
        foreach (var column in columns)
        {
            if (elementMap.TryGetValue(column.ColumnId, out int count))
            {
                for (int i = 0; i < count; i++)
                {
                    column.Elements.Add(new FormElement
                        {
                            ElementId = elementIdCounter++
                        });
                }
            }
        }

        rows[0].Columns.AddRange(new[] { columns[0], columns[1] });
        rows[1].Columns.Add(columns[2]);
        rows[2].Columns.Add(columns[3]);
        rows[3].Columns.AddRange(new[] { columns[4], columns[5] });
        rows[4].Columns.AddRange(new[] { columns[6], columns[7] });
        rows[5].Columns.Add(columns[8]);

        _testForm.Rows.AddRange(rows);
    }

    private void OnRowDropEnd(FluentDragEventArgs<FormRow> e)
    {
        var target = e.Target.Item;
        var source = e.Source.Item;

        int targetIndex = _testForm.Rows.IndexOf(target);

        _testForm.Rows.Remove(source);
        _testForm.Rows.Insert(targetIndex, source);
    }

    private void OnColumnDropEnd(FluentDragEventArgs<FormColumn> e)
    {
        var sourceRow = e.Source.Data as FormRow;
        var targetRow = e.Target.Data as FormRow;

        if (sourceRow is null || targetRow is null)
        {
            return;
        }

        var target = e.Target.Item;
        var source = e.Source.Item;
        int targetIndex = targetRow.Columns.IndexOf(target);

        if (sourceRow == targetRow)
        {
            sourceRow.Columns.Remove(source);
            sourceRow.Columns.Insert(targetIndex, source);
        }
        else
        {
            sourceRow.Columns.Remove(source);
            if (targetIndex != -1)
            {
                targetRow.Columns.Insert(targetIndex, source);
            }
            else
            {
                targetRow.Columns.Add(source);
            }
        }

        StateHasChanged();
    }

    private void OnDropElement(FluentDragEventArgs<FormElement> e)
    {
        var sourceColumn = e.Source.Data as FormColumn;
        var targetColumn = e.Target.Data as FormColumn;

        if (sourceColumn is null || targetColumn is null)
        {
            return;
        }

        var source = e.Source.Item;
        var target = e.Target.Item;


        int targetIndex = targetColumn.Elements.IndexOf(target);


        if (sourceColumn == targetColumn)
        {
            sourceColumn.Elements.Remove(source);
            sourceColumn.Elements.Insert(targetIndex, source);
        }
        else
        {
            sourceColumn.Elements.Remove(source);
            if (targetIndex != -1)
            {
                targetColumn.Elements.Insert(targetIndex, source);
            }
            else
            {
                targetColumn.Elements.Add(source);
            }
        }

        StateHasChanged();
    }

    public class Form
    {
        public int FormId { get; set; }
        public List<FormRow> Rows { get; set; } = [];
    }

    public class FormRow
    {
        public int RowId { get; set; }
        public List<FormColumn> Columns { get; set; } = [];
    }

    public class FormColumn
    {
        public int ColumnId { get; set; }
        public List<FormElement> Elements { get; set; } = [];
    }

    public class FormElement
    {
        public int ElementId { get; set; }
    }
}
